package com.Proxy.factory;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 创建代理工厂类：可以通过调用其中的方法，返回某个类的代理类
 */
public class ProxyFactory {
    /**
     * Object: 返回的代理类可以是任何类型
     * @param obj
     * @return
     */
    public static Object getProxyInstance(Object obj){  //obj:被代理类的对象

        /**
         * newProxyInstance(ClassLoader loader,Class<?>[] interfaces,reflect.InvocationHandler h):返回一个类的代理类
         *  newProxyInstance()方法的三个参数：
         *   loader:　　    一个ClassLoader对象，定义了由哪个ClassLoader对象来对生成的代理对象进行加载；就是获取一个类加载器。
         *          （一般我们自己写的类，无论与代理类或被代理类有没有关系，通过getClassLoader()方法获取的类加载器，都是AppClassLoader这个系统类加载器）
         *   interfaces:　　一个Interface对象的数组，表示的是我将要给我需要代理的对象提供一组什么接口，如果我提供了一组接口给它，那么这个代理对象就宣称实现了该接口(多态)，这样我就能调用这组接口中的方法了
         *              （至少必须包含一个与被代理类公共的接口，这里就是包含Person接口）
         *    h:　　         一个InvocationHandler对象，表示的是当我这个动态代理对象在调用方法的时候，会关联到哪一个InvocationHandler对象上
         */
        Object proxyInstance = Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new InvocationHandler() {
            /**
             * invoke(): 当我们通过代理类的对象，调用某个方法时，就会自动的调用invoke();将被代理类要执行的某个方法的功能就声明在invoke()中
             *
             * @param proxy 就是代理对象，newProxyInstance方法的返回对象
             * @param method 指代的是我们所要调用真实对象的某个方法的Method对象
             * @param args 指代的是调用真实对象某个方法时接受的参数
             * @return 返回结果
             * @throws Throwable 抛出一个异常
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("执行方法前的拓展输出");
                // obj:  被代理类的对象
                //args：传递的参数
                Object invoke = method.invoke(obj, args);
                System.out.println("执行方法后的拓展输出");
                return invoke;
            }
        });
        return proxyInstance;
    }
}
